SimpleIdMapping.java
package org.codefilarete.stalactite.mapping;
import java.util.function.Function;
import org.codefilarete.reflection.ReversibleAccessor;
import org.codefilarete.stalactite.engine.PersistExecutor.DefaultPersistExecutor.DefaultIsNewDeterminer;
import org.codefilarete.stalactite.mapping.id.assembly.SingleIdentifierAssembler;
import org.codefilarete.stalactite.mapping.id.manager.AlreadyAssignedIdentifierManager;
import org.codefilarete.stalactite.mapping.id.manager.IdentifierInsertionManager;
import org.codefilarete.stalactite.sql.ddl.structure.Table;
/**
* Entry point for single value (hence single-column primary key), as opposed to composed, about entity identifier mapping.
* Will mainly delegate its work to an {@link IdAccessor}, an {@link IdentifierInsertionManager} and a {@link SingleIdentifierAssembler}
*
* @author Guillaume Mary
* @see ComposedIdMapping
*/
public class SimpleIdMapping<C, I> implements IdMapping<C, I> {
private final AccessorWrapperIdAccessor<C, I> idAccessor;
private final IdentifierInsertionManager<C, I> identifierInsertionManager;
private final DefaultIsNewDeterminer<C> isNewDeterminer;
private final SingleIdentifierAssembler<I, ?> identifierMarshaller;
/**
* Main constructor
*
* @param idAccessor entry point to get/set id of an entity
* @param identifierInsertionManager defines the way the id is persisted into the database
* @param identifierMarshaller defines the way the id is read from the database
*/
public SimpleIdMapping(AccessorWrapperIdAccessor<C, I> idAccessor,
IdentifierInsertionManager<C, I> identifierInsertionManager,
SingleIdentifierAssembler<I, ?> identifierMarshaller) {
this.idAccessor = idAccessor;
this.identifierInsertionManager = identifierInsertionManager;
this.identifierMarshaller = identifierMarshaller;
if (identifierInsertionManager instanceof AlreadyAssignedIdentifierManager) {
this.isNewDeterminer = new AlreadyAssignedIdDeterminer(((AlreadyAssignedIdentifierManager<C, I>) identifierInsertionManager).getIsPersistedFunction());
} else if (identifierInsertionManager.getIdentifierType().isPrimitive()) {
this.isNewDeterminer = new PrimitiveIdDeterminer();
} else {
this.isNewDeterminer = new NullableIdDeterminer();
}
}
public SimpleIdMapping(ReversibleAccessor<C, I> identifierAccessor,
IdentifierInsertionManager<C, I> identifierInsertionManager,
SingleIdentifierAssembler identifierMarshaller) {
this(new AccessorWrapperIdAccessor<>(identifierAccessor), identifierInsertionManager, identifierMarshaller);
}
@Override
public AccessorWrapperIdAccessor<C, I> getIdAccessor() {
return idAccessor;
}
@Override
public IdentifierInsertionManager<C, I> getIdentifierInsertionManager() {
return identifierInsertionManager;
}
@Override
public boolean isNew(C entity) {
return isNewDeterminer.isNew(entity);
}
@Override
public <T extends Table<T>> SingleIdentifierAssembler<I, T> getIdentifierAssembler() {
return (SingleIdentifierAssembler<I, T>) identifierMarshaller;
}
/**
* For case where the identifier is a basic type (String, Long, ...)
*/
private class NullableIdDeterminer extends DefaultIsNewDeterminer<C> {
@Override
public boolean isNew(C entity) {
return idAccessor.getId(entity) == null;
}
}
/**
* For case where the identifier is a primitive type (long, int, ...)
*/
private class PrimitiveIdDeterminer extends DefaultIsNewDeterminer<C> {
@Override
public boolean isNew(C entity) {
return ((Number) idAccessor.getId(entity)).intValue() == 0;
}
}
/**
* For case where the identifier is already assigned : we have to delegate determination to a function
*/
private class AlreadyAssignedIdDeterminer extends DefaultIsNewDeterminer<C> {
private final Function<C, Boolean> isPersistedFunction;
private AlreadyAssignedIdDeterminer(Function<C, Boolean> isPersistedFunction) {
this.isPersistedFunction = isPersistedFunction;
}
@Override
public boolean isNew(C entity) {
return !isPersistedFunction.apply(entity);
}
}
}